#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
using namespace std;

namespace Calculator
{

    const string CalSep = " ";

    enum // 响应中如果运算出错我们的code字段就派上用场了， 以下就是可能出错的一些情况
    {
        Success = 0,
        DivZero,
        ModZero,
        Unknown,

    };
    // 我们在这里制定协议（其实就是书写结构化字段）

    class Response
    {
    public:
        Response() : _result(0), _code(0) {}
        Response(int result, int code = 0) : _result(result), _code(code)
        {
        }

        // bool Serialize(string &message)
        // {
        //     message = to_string(_result) + CalSep + to_string(_code);
        //     return true;
        // }

        // bool Deserialize(const string &message)
        // {
        //     int pos = message.find(CalSep);
        //     if (pos == string::npos)
        //         return false;

        //     _result = stoi(message.substr(0, pos));
        //     _code = stoi(message.substr(pos + CalSep.size()));
        //     return true;
        // }

        bool Serialize(string &message)
        {
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;
            Json::FastWriter writer;
            message = writer.write(root);
            return true;
        }

        bool Deserialize(const string &message)
        {
            Json::Value root;
            Json::Reader reader;
            reader.parse(message, root);
            _result = root["result"].asInt();
            _code = root["code"].asInt();
            return true;
        }

        int GetResult() { return _result; }
        int GetCode() { return _code; }

    private:
        int _result;
        int _code;
    };
    class Request
    {
    public:
        Request() : _data_x(0), _data_y(0), _oper(0) {}
        Request(int data_x, int data_y, char oper) : _data_x(data_x), _data_y(data_y), _oper(oper)
        {
        }

        bool Serialize(string &message)
        {
            Json::Value root;
            root["data_x"] = _data_x;
            root["data_y"] = _data_y;
            root["oper"] = _oper;
            Json::FastWriter writer;
            message = writer.write(root);
            return true;
        }

        bool Deserialize(const string &message)
        {
            // 找到两个空格就可以很好的反序列化有效载荷
            Json::Value root;
            Json::Reader reader;
            reader.parse(message, root);
            _data_x = root["data_x"].asInt();
            _data_y = root["data_y"].asInt();
            _oper = root["oper"].asInt();
            return true;
        }

        // bool Serialize(string &message)
        // {
        //     message = to_string(_data_x) + CalSep + _oper + CalSep + to_string(_data_y);
        //     return true;
        // }

        // bool Deserialize(const string &message)
        // {
        //     // 找到两个空格就可以很好的反序列化有效载荷
        //     int left = message.find(CalSep);
        //     if (left == string::npos)
        //         return false;
        //     int right = message.rfind(CalSep);
        //     if (right == string::npos)
        //         return false;

        //     _data_x = stoi(message.substr(0, left));
        //     _data_y = stoi(message.substr(right + CalSep.size()));
        //     string stroper = message.substr(left + CalSep.size(), right - (left + CalSep.size()));

        //     if (stroper.size() != 1)
        //         return false;
        //     _oper = stroper[0];
        //     return true;
        // }

        shared_ptr<Calculator::Response> Result()
        {
            switch (_oper)
            {
            case '+':
                return make_shared<Calculator::Response>(_data_x + _data_y);
                break;
            case '-':
                return make_shared<Calculator::Response>(_data_x - _data_y);
                break;
            case '*':
                return make_shared<Calculator::Response>(_data_x * _data_y);
                break;
            case '/':
            {
                if (_data_y == 0)
                    return make_shared<Calculator::Response>(0, DivZero);
                else
                    return make_shared<Calculator::Response>(_data_x / _data_y);
                break;
            }
            case '%':
            {
                if (_data_y == 0)
                    return make_shared<Calculator::Response>(0, ModZero);
                else
                    return make_shared<Calculator::Response>(_data_x % _data_y);
                break;
            }
            default:
                return make_shared<Calculator::Response>(0, Unknown);
                break;
            }
        }

        int GetX() { return _data_x; }
        int GetY() { return _data_y; }
        char GetOp() { return _oper; }

    private:
        int _data_x;
        int _data_y;
        char _oper;
    };

}

// namespace Calculator
// {

//     enum // 响应中如果运算出错我们的code字段就派上用场了， 以下就是可能出错的一些情况
//     {
//         Success = 0,
//         DivZero,
//         ModZero,
//         Unknown,

//     };
//     // 我们在这里制定协议（其实就是书写结构化字段）
//     class Request
//     {
//     public:
//         Request() : _data_x(0), _data_y(0), _oper(0) {}
//         Request(int data_x, int data_y, char oper) : _data_x(data_x), _data_y(data_y), _oper(oper)
//         {
//         }

//         shared_ptr<Response> Result()
//         {
//             switch (_oper)
//             {
//             case '+':
//                 return make_shared<Response>(_data_x + _data_y);
//                 break;
//             case '-':
//                 return make_shared<Response>(_data_x - _data_y);
//                 break;
//             case '*':
//                 return make_shared<Response>(_data_x * _data_y);
//                 break;
//             case '/':
//             {
//                 if (_data_y == 0)
//                     return make_shared<Response>(0, DivZero);
//                 else
//                     return make_shared<Response>(_data_x / _data_y);
//                 break;
//             }
//             case '%':
//             {
//                 if (_data_y == 0)
//                     return make_shared<Response>(0, ModZero);
//                 else
//                     return make_shared<Response>(_data_x % _data_y);
//                 break;
//             }
//             default:
//                 return make_shared<Response>(0, Unknown);
//                 break;
//             }
//         }

//         int GetX() { return _data_x; }
//         int GetY() { return _data_y; }
//         char GetOp() { return _oper; }

//     private:
//         int _data_x;
//         int _data_y;
//         char _oper;
//     };

//     class Response
//     {
//     public:
//         Response() : _result(0), _code(0) {}
//         Response(int result, int code) : _result(result), _code(code)
//         {
//         }

//         int GetResult() { return _result; }
//         int GetCode() { return _code; }

//     private:
//         int _result;
//         int _code;
//     };
// }